using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Decav.Gatsb.Mobile
{
    /// <summary>
    /// Reads a multipart MIME message.
    /// </summary>
    public class MultipartReader
    {
        public MultipartReader(StreamReader reader, string boundary)
        {
            if (reader == null)
                throw new ArgumentNullException("reader");

            if (boundary == null)
                throw new ArgumentNullException("boundary");

            _boundary = string.Format("--{0}", boundary);
            _reader = reader;
        }

        private string _boundary;
        private StreamReader _reader;

        /// <summary>
        /// Reads file attachments from the multipart message.
        /// </summary>
        /// <returns>The file attachments that were read.</returns>
        public FileAttachment[] Read()
        {
            // Read to the first boundry
            while (_reader.ReadLine().Trim() != _boundary) ;

            List<FileAttachment> attachments = new List<FileAttachment>();
            FileAttachment attachment = null;
            while (ReadAttachment(out attachment))
                attachments.Add(attachment);

            if (attachment != null)
                attachments.Add(attachment);

            return attachments.ToArray();
        }

        private const string ContentTransferHeaderName = "Content-Transfer-Encoding";

        private bool ReadAttachment(out FileAttachment attachment)
        {
            SmtpMailHeader header = SmtpMailHeader.Parse(_reader);
            string endBoundry = null;

            string buffer = null;
            StringBuilder builder = new StringBuilder();
            while (!(buffer = _reader.ReadLine()).StartsWith(_boundary)) // read all the buffer
                builder.AppendLine(buffer);

            endBoundry = buffer;

            string fileName = header.Contains("Content-Location") ? header["Content-Location"][0].Trim() : "default.xxx";
            if (header.Contains(ContentTransferHeaderName) && header[ContentTransferHeaderName][0].ToLower() == "base64")
            {
                // Read base64
                attachment = new FileAttachment(fileName, header.ContentType,
                    Convert.FromBase64String(builder.ToString()));
            }
            else
            {
                // Read plain text.
                attachment = new FileAttachment(fileName, header.ContentType,
                    Encoding.Default.GetBytes(builder.ToString()));
            }

            if (endBoundry.StartsWith(string.Format("{0}--", _boundary))) // end of file
                return false;
            else
                return true; // normal boundry (more parts)
        }
    }
}
